using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[Serializable]
public class HeroData
{
    public int id;
    public int hp;
    public int ip;
    public int king;
    public string name;
    public int step=3;
    public int attack=1;
    public int body_move = 5;
}

public class Hero : MonoBehaviour
{
    public Transform mCacheTrans;

    public bool mHasAction; 
    SpriteRenderer mSprite;
    List<Vector3> mNodes = new List<Vector3>();
    public bool mRunning = false;
    //public bool mHasMove = false;


    public int mID { private set; get; }
    public int mHP { private set; get; }
    public int mIP { private set; get; }
    public int mKing { private set; get; }
    public string mName { private set; get; }
    public int mBodyMove = 5;

    public HeroData mDebugData;
    public UIHero mHeroUI;
    public Action mMoveEnd;
    Transform mCameraTrans;

    void Awake()
    {
        mSprite = GetComponent<SpriteRenderer>();
        mCacheTrans = this.transform;   

        SetData(mDebugData);
        HeroManager.AddHero(this);
    }

    private void OnDestroy()
    {
        HeroManager.RemoveHero(this);
    }

    private void Start()
    {
        transform.position = GameTool.GetPosInt(transform.position);
        //SetData(mDebugData);

        mHeroUI = ResourceManager.Instance.CreateHeroUI();
        mHeroUI.mCacheTrans.position = mCacheTrans.position;
        mHeroUI.SetData(this);
        mHeroUI.UpdateUI();

        mCameraTrans = Camera.main.transform;
    }

    public void SetData(HeroData data)
    {
        mID = data.id;
        mHP = data.hp;
        mKing = data.king;
        mIP = data.ip;
        mName = data.name;
        mBodyMove = data.body_move;
        //mFlag.color = GameTool.GetFlagColor(mKing);

        //mHeroUI.SetData(this);
        if (mID == GameFacade.mLocalHero)
        {
            GameFacade.LocalKing = mKing;
        }
    }

    public void CameraFocus()
    {
        mCameraTrans.position = mCacheTrans.position + Vector3.forward * -10;
    }

    public bool GetActionState()
    { 
        return mHasAction;
    }

    public void SetActionState(bool v)
    {
        mHasAction = v; 
        mSprite.color = !mHasAction ? Color.white : Color.grey;
    }

    public void DoAttack(Hero beAttack)
    {
        mIP -= 1;
        if (mHeroUI)
            mHeroUI.UpdateUI();
        beAttack.BeAttack();
    }

    public void BeAttack()
    {
        mHP -= 1;
        if (mHeroUI)
            mHeroUI.UpdateUI();
    }

    public void DoMove(Vector3 wpos,bool dest_skip1=false)
    {
        mRunning = true;
        //var nodes = FindPath(origin, pos, step + attack);
        var nodes = Pathfinding2D.Instance.FindPath(transform.position, wpos, mDebugData.step);
        if (dest_skip1 && nodes.Count > 0)
        {
            nodes.RemoveAt(nodes.Count-1);
        }
        if (nodes.Count > 0 && nodes.Count <= mDebugData.step + 1)
        {
            mNodes.Clear();
            for (int i = 0; i < nodes.Count; i++)
            {
                mNodes.Add(nodes[i].ToV2());
            }
        }
    }

    public void DoMove(List<Node2D> nodes)
    {
        mRunning = true;
        if (nodes.Count > 0 && nodes.Count <= mDebugData.step + 1)
        {
            mNodes.Clear();
            for (int i = 0; i < nodes.Count; i++)
            {
                mNodes.Add(nodes[i].ToV2());
            }
        }
    }

    public bool CheckFormSingle(Hero h)
    {
        //var rs = FormationManager.Instance.CheckForm2(h.mCacheTrans.position);
        var startPos = GameTool.GetPosInt(h.mCacheTrans.position);
        List<Vector2> pos_list = new List<Vector2>();
        pos_list.Add(startPos + Vector2.right * 2);
        pos_list.Add(startPos + Vector2.right * 2 + Vector2.up * 2);
        pos_list.Add(startPos + Vector2.up * 2);

        List<Hero> hs = new List<Hero>();
        hs.Add(h);
        int count = 0;
        for (int i = 0; i < pos_list.Count; i++)
        {
            var pos = pos_list[i];
            foreach (var h1 in HeroManager.Instance.GetHeros())
            {
                var wpos = h1.mCacheTrans.position;
                wpos = GameTool.GetPosInt(wpos);
                if (Vector2.Distance(wpos, pos) < 0.5f && h1.mKing==mKing)
                {
                    hs.Add(h1);
                    count++;
                    break;
                }
            }
        }
        var rs = count == pos_list.Count;
        if (rs)
        {
            //pos_list.Insert(0, startPos);
            //Debug.DrawLine(pos_list[pos_list.Count - 1], pos_list[0], Color.red, 60);
            //for (int i = 1; i < pos_list.Count; i++)
            //{
            //    Debug.DrawLine(pos_list[i - 1], pos_list[i], Color.red, 60);
            //}
            FormationManager.Instance.CreateForm2(startPos, hs);
        }
        return rs;
    }

    public bool CheckForm()
    {
        bool rs = false; 
        var hs = HeroManager.Instance.GetHeros();
        for (int i = 0; i < hs.Count; i++)
        {
            rs = CheckFormSingle(hs[i]);
            if (rs)
            {
                break;
            }
        }

        if (!rs)
        {
            FormationManager.Instance.RemoveForm2(this);
        }
        return rs;
    }

    void MoveEnd()
    {
        //mHP -= 1;
        //if (mHeroUI)
        //    mHeroUI.UpdateUI();

        CheckForm();

        if (mMoveEnd != null)
        {
            mMoveEnd();
        }

    }


    public void TickUpdate()
    {
        //mCD += Time.deltaTime;
        //if (mCD>=mDebugData.action_cd)
        //{
        //    mCD = 0;
        //    var e = HeroManager.Instance.FindNearEnemy(this);
        //    if (e != null)
        //    { 
        //        DoMove(e.mCacheTrans.position,true);
        //    }
        //}


        if (mNodes.Count > 0)
        {
            var p = mCacheTrans.position;
            var n = mNodes[0];
            mCacheTrans.position += (n - p).normalized * 5 * Time.deltaTime;
            if (Vector3.Distance(p, n) < 0.1f)
            {
                mCacheTrans.position = n;
                mNodes.RemoveAt(0);
            }
        }
        else
        {
            if (mRunning)
            {
                mRunning = false;
                SetActionState(true);
                //mHasMove = true;
                Debug.LogError("Hero Finish=" + name);
                MoveEnd();

            }
        }

        mHeroUI.mCacheTrans.position = mCacheTrans.position;
    }


#if UNITY_EDITOR
    private void OnDrawGizmos()
    {
        var text = $"{mDebugData.id}_{mDebugData.name}_{mDebugData.king}";
        Handles.Label(transform.position, text,new GUIStyle() { fontSize=14,alignment = TextAnchor.LowerCenter});
        name = text;
    }
#endif
}
